package org.grayrabbit.cloud.core.module;

import org.apache.commons.lang.StringUtils;
import org.grayrabbit.cloud.core.biz.BizAbstractModule;
import org.grayrabbit.cloud.core.handler.HandlerException;
import org.grayrabbit.cloud.core.rpc.Argument;
import org.grayrabbit.cloud.core.rpc.Channel;
import org.grayrabbit.cloud.core.rpc.ChannelException;
import org.grayrabbit.cloud.core.rpc.ChannelFactory;
import org.grayrabbit.cloud.core.rpc.Result;
import org.grayrabbit.cloud.core.rpc.URLException;


/**
 * @author sys53
 * @version 1.0
 * @created 11-六月-2011 16:52:19
 */
public abstract class ChannelModule<R extends Result, A extends Argument>
		extends BizAbstractModule {

	protected Channel<R> channel;
	protected ChannelFactory<R> factory;

	public ChannelModule() {

	}

	public ChannelModule(String name, String url)
			throws ModuleConstructException {
		this.name = name;
		build(url);
	}

	private void build(String url) throws ModuleConstructException {
		assert (!StringUtils.isBlank(url));
		if (StringUtils.isBlank(url))
			throw new ModuleConstructException(
					String.format("Channel(%s) url can't be null",
							new Object[] { this.name }));
		try {
			this.factory = getChannelFactory();
			assert (this.factory != null);
			if (this.factory == null)
				throw new ModuleConstructException(String.format(
						"Channel(%s) factory can't be null",
						new Object[] { this.name }));
			this.channel = this.factory.alloc(url);
		} catch (ChannelException e) {
			throw new ModuleConstructException(e);
		} catch (URLException e) {
			throw new ModuleConstructException(e);
		}
	}

	/**
	 * 
	 * @param param
	 * @throws ModuleConstructException
	 */
	public void construct(String name) throws ModuleConstructException {
		super.construct(name);
		build(getChannelUrl());
	}

	public void deconstruct() {
		try {
			if (this.channel != null)
				this.factory.free(this.channel);
		} catch (ChannelException localChannelException) {
		}
	}

	protected abstract String getChannelUrl();

	protected abstract ChannelFactory<R> getChannelFactory();

	public R submit(A argument) throws ModuleException {
		try {
			return this.channel.invoke(argument);
		} catch (ChannelException e) {
			throw new ModuleException(e);
		} catch (HandlerException e) {
			throw new ModuleException(e);
		}

	}

}